package host.springboot.framework.core.constant;

import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.format.ResolverStyle;
import java.time.format.SignStyle;

import static java.time.temporal.ChronoField.*;

/**
 * 规则常量
 *
 * <p>该类用于存储预置正则表达式信息
 * <p><a href="https://c.runoob.com/front-end/854/">点击查看常用正则表达式</a>
 *
 * @author JiYinchuan
 * @since 1.0.0
 */
public class PatternConstant {

    /**
     * 电话号码正则表达式
     *
     * <p>支持手机号码/3-4位区号/7-8位直播号码/1－4位分机号
     */
    public static final String PHONE = "((\\d{11})|^((\\d{7,8})|(\\d{4}|\\d{3})-(\\d{7,8})|(\\d{4}|\\d{3})-(\\d{7,8})-" +
            "(\\d{4}|\\d{3}|\\d{2}|\\d{1})|(\\d{7,8})-(\\d{4}|\\d{3}|\\d{2}|\\d{1}))$)";

    /**
     * 邮箱正则表达式
     */
    public static final String EMAIL = "^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$";

    /**
     * 身份证号正则表达式
     */
    public static final String ID_NUMBER = "(^\\d{15}$)|(^\\d{18}$)|(^\\d{17}(\\d|X|x)$)";

    /**
     * 账号正则表达式
     *
     * <p>字母开头, 允许 [5-16] 字节, 允许字母数字下划线
     */
    public static final String ACCOUNT = "^[a-zA-Z][a-zA-Z0-9_]{4,15}$";

    /**
     * 密码正则表达式
     *
     * <p>以字母开头, 长度在 [6~18] 之间, 只能包含字母、数字和下划线
     */
    public static final String PASSWORD = "^[a-zA-Z]\\w{5,17}$";

    /**
     * 强密码正则表达式
     *
     * <p>必须包含大小写字母和数字的组合, 不能使用特殊字符, 长度在 [8-10] 之间
     */
    public static final String STRONG_PASSWORD = "^(?=.*\\d)(?=.*[a-z])(?=.*[A-Z])[a-zA-Z0-9]{8,10}$";

    /**
     * 强密码正则表达式
     *
     * <p>必须包含大小写字母和数字的组合, 可以使用特殊字符, 长度在 [8-10] 之间
     */
    public static final String STRONG_PASSWORD_WITH_SPECIAL = "^(?=.*\\d)(?=.*[a-z])(?=.*[A-Z])[a-zA-Z0-9]{8,10}$";

    /**
     * 时间格式
     *
     * <p>Pattern:
     * <ul>
     *     <li><b>yyyy-MM-dd HH:mm:ss</b> - NORM_DATETIME_PATTERN</li>
     *     <li><b>yyyy-MM-dd</b> - NORM_DATE_PATTERN</li>
     *     <li><b>HH:mm:ss</b> - NORM_TIME_PATTERN</li>
     *     <li><b>yyyy</b> - NORM_YEAR_PATTERN</li>
     *     <li><b>yyyy-MM</b> - NORM_YEARMONTH_PATTERN</li>
     *     <li><b>MM-dd</b> - NORM_MONTHDAY_PATTERN</li>
     * </ul>
     * <p>Formatter:
     * <ul>
     *     <li><b>yyyy-MM-dd HH:mm:ss</b> - NORM_DATETIME_FORMATTER</li>
     *     <li><b>yyyy-MM-dd</b> - NORM_DATE_FORMATTER</li>
     *     <li><b>HH:mm:ss</b> - NORM_TIME_FORMATTER</li>
     *     <li><b>yyyy-MM-dd HH:mm:ss+HH:MM:ss</b> - NORM_OFFSET_DATETIME_FORMATTER</li>
     *     <li><b>yyyy-MM-dd HH:mm:ss+HH:MM:ss[ZoneRegionId()]</b> - NORM_ZONED_DATETIME_FORMATTER</li>
     *     <li><b>yyyy</b> - NORM_YEAR_FORMATTER</li>
     *     <li><b>yyyy-MM</b> - NORM_YEARMONTH_FORMATTER</li>
     *     <li><b>MM-dd</b> - NORM_MONTHDAY_FORMATTER</li>
     *     <li><b>HH:mm:ss+HH:MM:ss</b> - NORM_OFFSET_TIME_FORMATTER</li>
     * </ul>
     *
     * @author JiYinchuan
     * @since 1.0.0
     */
    public static abstract class Date {

        /**
         * 时间格式 [yyyy-MM-dd HH:mm:ss]
         */
        public static final String NORM_DATETIME_PATTERN = "yyyy-MM-dd HH:mm:ss";
        public static final DateTimeFormatter NORM_DATETIME_FORMATTER;

        /**
         * 时间格式 [yyyy-MM-dd HH:mm:ss+HH:MM:ss]
         */
        public static final DateTimeFormatter NORM_OFFSET_DATETIME_FORMATTER;

        /**
         * 时间格式 [yyyy-MM-dd HH:mm:ss+HH:MM:ss[ZoneRegionId()]]
         */
        public static final DateTimeFormatter NORM_ZONED_DATETIME_FORMATTER;

        /**
         * 时间格式 [yyyy-MM-dd]
         */
        public static final String NORM_DATE_PATTERN = "yyyy-MM-dd";
        public static final DateTimeFormatter NORM_DATE_FORMATTER;

        /**
         * 时间格式 [yyyy]
         */
        public static final String NORM_YEAR_PATTERN = "yyyy";
        public static final DateTimeFormatter NORM_YEAR_FORMATTER;

        /**
         * 时间格式 [yyyy-MM]
         */
        public static final String NORM_YEARMONTH_PATTERN = "yyyy-MM";
        public static final DateTimeFormatter NORM_YEARMONTH_FORMATTER;

        /**
         * 时间格式 [MM-dd]
         */
        public static final String NORM_MONTHDAY_PATTERN = "MM-dd";
        public static final DateTimeFormatter NORM_MONTHDAY_FORMATTER;

        /**
         * 时间格式 [HH:mm:ss]
         */
        public static final String NORM_TIME_PATTERN = "HH:mm:ss";
        public static final DateTimeFormatter NORM_TIME_FORMATTER;

        /**
         * 时间格式 [HH:mm:ss+HH:MM:ss]
         */
        public static final DateTimeFormatter NORM_OFFSET_TIME_FORMATTER;

        static {
            // yyyy-MM-dd
            NORM_DATE_FORMATTER = DateTimeFormatter.ISO_LOCAL_DATE;
            // HH:mm:ss
            NORM_TIME_FORMATTER = new DateTimeFormatterBuilder()
                    .parseCaseInsensitive()
                    .appendValue(HOUR_OF_DAY, 2)
                    .appendLiteral(':')
                    .appendValue(MINUTE_OF_HOUR, 2)
                    .optionalStart()
                    .appendLiteral(':')
                    .appendValue(SECOND_OF_MINUTE, 2)
                    .toFormatter()
                    .withResolverStyle(ResolverStyle.STRICT);
            // yyyy-MM-dd HH:mm:ss
            NORM_DATETIME_FORMATTER = new DateTimeFormatterBuilder()
                    .parseCaseInsensitive()
                    .append(NORM_DATE_FORMATTER)
                    .appendLiteral(' ')
                    .append(NORM_TIME_FORMATTER)
                    .toFormatter()
                    .withResolverStyle(ResolverStyle.STRICT);
            // yyyy
            NORM_YEAR_FORMATTER = new DateTimeFormatterBuilder()
                    .appendValue(YEAR, 4, 10, SignStyle.EXCEEDS_PAD)
                    .toFormatter()
                    .withResolverStyle(ResolverStyle.STRICT);
            // yyyy-MM
            NORM_YEARMONTH_FORMATTER = new DateTimeFormatterBuilder()
                    .append(NORM_YEAR_FORMATTER)
                    .appendLiteral('-')
                    .appendValue(MONTH_OF_YEAR, 2)
                    .toFormatter()
                    .withResolverStyle(ResolverStyle.STRICT);
            // MM-dd
            NORM_MONTHDAY_FORMATTER = new DateTimeFormatterBuilder()
                    .appendValue(MONTH_OF_YEAR, 2)
                    .appendLiteral('-')
                    .appendValue(DAY_OF_MONTH, 2)
                    .toFormatter()
                    .withResolverStyle(ResolverStyle.STRICT);
            // yyyy-MM-dd HH:mm:ss+HH:MM:ss
            NORM_OFFSET_DATETIME_FORMATTER = new DateTimeFormatterBuilder()
                    .parseCaseInsensitive()
                    .append(NORM_DATETIME_FORMATTER)
                    .appendOffsetId()
                    .toFormatter()
                    .withResolverStyle(ResolverStyle.STRICT);
            // yyyy-MM-dd HH:mm:ss+HH:MM:ss[ZoneRegionId()]
            NORM_ZONED_DATETIME_FORMATTER = new DateTimeFormatterBuilder()
                    .append(NORM_OFFSET_DATETIME_FORMATTER)
                    .optionalStart()
                    .appendLiteral('[')
                    .parseCaseSensitive()
                    .appendZoneRegionId()
                    .appendLiteral(']')
                    .toFormatter()
                    .withResolverStyle(ResolverStyle.STRICT);
            // HH:mm:ss+HH:MM:ss
            NORM_OFFSET_TIME_FORMATTER = new DateTimeFormatterBuilder()
                    .parseCaseInsensitive()
                    .append(NORM_TIME_FORMATTER)
                    .appendOffsetId()
                    .toFormatter()
                    .withResolverStyle(ResolverStyle.STRICT);
        }
    }
}
